package polybook.utils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import polybook.model.Person;
import polybook.model.comparator.DegreComparator;
import polybook.model.comparator.NomPrenomComparator;

/**
 * Classe regroupant tous les tris ou algorithmes basés sur des mélanges de
 * tableaux
 *
 * @author epulapp
 */
public class SortUtils {

    /**
     * Valeur du comparateur par nombre d'amis pour deux personnes
     */
    public final static Comparator compParDegre = new DegreComparator();
    /**
     * Valeur du comparateur par nom/prénom pour deux personnes
     */
    public final static Comparator compParNomPrenom = new NomPrenomComparator();

    /**
     * Algorithme de mélange de list (tri aléatoire)
     *
     * @param <E> Le type de donnée contenu dans la liste
     * @param list La liste à mélanger
     * @return Une nouvelle liste mélangée
     */
    public static <E> List<E> randomSort(List<E> list) {
        // Initialisation : création de la nouvelle liste et de l'index aléatoire
        ArrayList<E> copyList = new ArrayList<E>();
        int randomIndex;
        for (int i = 0; i < list.size(); i++) {
            // Pour chaque élément de la liste initiale on le range, avec un index aléatoire, dans la nouvelle liste
            randomIndex = (int) Math.round(Math.random() * (list.size() - 1));
            do {
                // On essai de trouver un index qui n'est pas encore occupé
                randomIndex = (randomIndex == list.size() - 1) ? 0 : randomIndex + 1;
            } while (copyList.contains(list.get(randomIndex)));
            // Puis on ajoute l'element à l'indice aléatoire libre trouvé
            copyList.add(i, list.get(randomIndex));
        }
        return (List<E>) copyList;
    }

    /**
     * Algorithme de tri à bulle pour un tableau de personnes
     *
     * @param listPerson Un tableau de personnes
     */
    public static void BubbleSortByName(ArrayList<Person> listPerson) {
        // TODO : ajouter un parametre sur l'interface Comparator
        // TODO : virer le type Person, le trie ne doit pas dependre du reste 
        // du projet (voir exemple sur randomSort)
        for (int i = 0; i <= (listPerson.size() - 2); i++) {
            for (int j = (listPerson.size() - 1); i < j; j--) {
                if (listPerson.get(j).getNom().compareTo(listPerson.get(j - 1).getNom()) < 0) {
                    Person persTemp = listPerson.get(j - 1);
                    listPerson.set(j - 1, listPerson.get(j));
                    listPerson.set(j, persTemp);
                } else {
                    if (listPerson.get(j).getNom().compareTo(listPerson.get(j - 1).getNom()) == 0
                            && listPerson.get(j).getPrenom().compareTo(listPerson.get(j - 1).getPrenom()) < 0) {
                        Person persTemp = listPerson.get(j - 1);
                        listPerson.set(j - 1, listPerson.get(j));
                        listPerson.set(j, persTemp);
                    }
                }
            }
        }
    }

    /**
     * Algorithme de tri à bulle pour un tableau de personnes
     *
     * @param listPerson Un tableau de personnes
     */
    public static void BubbleSortByFriends(ArrayList<Person> listPerson) {
        // TODO : idem que BubbleSort
        for (int i = 0; i <= (listPerson.size() - 2); i++) {
            for (int j = (listPerson.size() - 1); i < j; j--) {
                //Calcul du degré des personnes
                Integer degrePers1 = listPerson.get(j).getFriendList().size();
                Integer degrePers2 = listPerson.get(j - 1).getFriendList().size();

                if (degrePers1.compareTo(degrePers2) < 0) {
                    Person persTemp = listPerson.get(j - 1);
                    listPerson.set(j - 1, listPerson.get(j));
                    listPerson.set(j, persTemp);
                }
            }
        }
    }
}
